Implement caching among fingerprint resolutions
This commit adds support for caching the resolved value of a fingerprint among
calls to `resolve`. Due to the recursive nature of a fingerprint, it means that
`resolve` is currently executed a very large number of times for packages which
at transitively dependend up on many times. By caching the returned value of a
fingerprint we're able to prevent extraneous calls into the filesystem or
extraneous hashing.
This also adds an `Arc` to share a `Fingerprint` among all its dependencies as
each fingerprint stores a list of fingerprints that it depends on, and if
they're not shared then the cache isn't exactly the most helpful!
For a noop `cargo build` on Servo (e.g. everything was already built), this
decreased Cargo's runtime from 5s to ~4.5s